import pandas as pd
import numpy as np

class NaiveBayes:
    def __init__(self):
        self.classes = None
        self.mean = {}
        self.variance = {}
        self.prior = {}

    def fit(self, X, y):
        self.classes = np.unique(y) 
        n_features = X.shape[1]

        
        for cls in self.classes:
            X_cls = X[y == cls]
            self.mean[cls] = X_cls.mean(axis=0)    
            self.variance[cls] = X_cls.var(axis=0)  
            self.prior[cls] = len(X_cls) / len(y)   

    def predict(self, X):

        predictions = []
        for x in X:
            class_probabilities = {}
            for cls in self.classes:
                prior = self.prior[cls]
                likelihood = self._calculate_likelihood(x, cls)
                posterior = prior * likelihood
                class_probabilities[cls] = posterior
            
            predicted_class = max(class_probabilities, key=class_probabilities.get)
            predictions.append(predicted_class)
        return np.array(predictions)

    def _calculate_likelihood(self, x, cls):
       
        mean = self.mean[cls]
        variance = self.variance[cls]

        exponent = np.exp(-((x - mean) ** 2) / (2 * variance))
        coeff = 1 / np.sqrt(2 * np.pi * variance)
        likelihood = coeff * exponent
        return np.prod(likelihood)  



if __name__ == '__main__':

    iris_data = pd.read_csv('iris.csv', header=None)
    X = iris_data.iloc[:, :-1].values 
    y = iris_data.iloc[:, -1].values    

    labels, y_numeric = np.unique(y, return_inverse=True)

    nb = NaiveBayes()
    nb.fit(X, y_numeric)

    predictions = nb.predict(X)

    for i in range(len(predictions)):
        print(f"真实标签: {labels[y_numeric[i]]}, 预测标签: {labels[predictions[i]]}")